package practice;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Stack;

public class calc {
    public static void main(String [] args) {
        String str = "6*-8";
        calc c = new calc();
        System.out.println(c.compute(c.strToExpressionArr(str)));
    }

    //把表达式转换为数组
    private ArrayList<String> strToExpressionArr(String str) {
        ArrayList<String> list = new ArrayList<>();
        boolean isNe = false;
        str = str.replace(" ", "");
        // 头尾判断
        if(str.charAt(0) == '+' ||
                str.charAt(0) == '*' ||
                str.charAt(0) == '/' ||
                str.charAt(str.length() - 1) == '-' ||
                str.charAt(str.length() - 1) == '+' ||
                str.charAt(str.length() - 1) == '*' ||
                str.charAt(str.length() - 1) == '/'){
            return null;
        }
        // 括号统计
        int count = 0;
        for (int i = 0; i < str.length(); i++) {
            if(str.charAt(i) == '-'){
                if(i == 0 || str.charAt(i - 1) < '0' || str.charAt(i - 1) > '9'){
                    list.add("(");
                    list.add("0");
                    isNe = true;
                }
            }
            if(str.charAt(i) == '-' ||
                    str.charAt(i) == '+' ||
                    str.charAt(i) == '*' ||
                    str.charAt(i) == '/' ||
                    str.charAt(i) == '(' ||
                    str.charAt(i) == ')'){
                if(str.charAt(i) == '(') count ++;
                else if(str.charAt(i) == ')') count --;
                else{
                    // 运算符,前一个不能为运算符
                    if ( list.size() > 0 && (list.get(list.size() - 1).equals("-") ||
                            list.get(list.size() - 1).equals("+") ||
                            list.get(list.size() - 1).equals("*") ||
                            list.get(list.size() - 1).equals("/"))){
                        return null;
                    }
                }
                list.add(str.substring(i, i+1));
            } else if ((str.charAt(i) >= '0' && str.charAt(i) <= '9') || str.charAt(i) == '.' ){
                int l = i;
                for(;i < str.length() - 1 && ((str.charAt(i + 1) >= '0' && str.charAt(i + 1) <= '9') || str.charAt(i + 1) == '.');i++);
                StringBuilder num = new StringBuilder(str.substring(l, i + 1));
                if(num.charAt(0) == '.'){
                    num = new StringBuilder("0").append(num);
                }
                if(num.charAt(num.length() - 1) == '.'){
                    num.append("0");
                }
                // 校验num数字合法性
                try{
                    Float.parseFloat(num.toString());
                } catch (Exception e){
                    return null;
                }
                list.add(num.toString());
                if (isNe){
                    list.add(")");
                    isNe = false;
                }

            }
            // 非法字符
            else{
                return null;
            }
        }
        //括号不匹配
        if(count != 0){
            return null;
        }
        System.out.println(list);
        return list;
    }

    private float compute(ArrayList<String> list) {
        Stack<Float> numStack = new Stack<>();
        Stack<Character> opStack = new Stack<>();

        for (String ele: list) {

            //如果是数字，进入数字栈
            if (isNumber(ele)) {
                numStack.push(Float.parseFloat(ele));
            }
            //以下是符号
            //遇到加减号，把栈顶的符号都处理完，直到遇到（左括号和栈空情况，最后把提取到的符号压入栈
            else if (ele.charAt(0) == '+' || ele.charAt(0) == '-') {
                while (!opStack.isEmpty() && opStack.peek() != '(') {
                    float b = numStack.pop();
                    float a = numStack.pop();
                    numStack.push(getAnswer(a, opStack.pop(), b));
                }

//                if (!opStack.isEmpty() && opStack.peek() == '(')
//                    opStack.pop();

                opStack.push(ele.charAt(0));
            }
            //遇到乘除号，把前面的乘除号处理完，最后把提取到的符号压入栈
            else if (ele.charAt(0) == '*' || ele.charAt(0) == '/') {
                while (!opStack.isEmpty() && opStack.peek() != '(' &&
                        opStack.peek() != '+' && opStack.peek() != '-') {
                    float b = numStack.pop();
                    float a = numStack.pop();
                    numStack.push(getAnswer(a, opStack.pop(), b));
                }

//                if (!opStack.isEmpty() && opStack.peek() == '(')
//                    opStack.pop();

                opStack.push(ele.charAt(0));
            }
            //遇到左括号，只进栈
            else if (ele.charAt(0) == '(') {
                opStack.push(ele.charAt(0));
            }
            //遇到右括号，只处理栈顶全部符号
            else if (ele.charAt(0) == ')') {
                while (!opStack.isEmpty() && opStack.peek() != '(') {
                    float b = numStack.pop();
                    float a = numStack.pop();
                    numStack.push(getAnswer(a, opStack.pop(), b));
                }

                if (!opStack.isEmpty() && opStack.peek() == '(')
                    opStack.pop();
            }
        }

        //最后没有以右括号结尾的表达式还得另外把剩下的符号处理完
        while (!opStack.isEmpty()) {
            float b = numStack.pop();
            float a = numStack.pop();
            numStack.push(getAnswer(a, opStack.pop(), b));
        }
        BigDecimal b   =   new   BigDecimal(numStack.peek());
        return b.setScale(2,   BigDecimal.ROUND_HALF_UP).floatValue();
    }

    //判断是否数字
    private boolean isNumber(String s) {
        if (s.charAt(0) < '0' || s.charAt(0) > '9')
            return false;
        return true;
    }

    //四则运算
    private float getAnswer(float a, char operator, float b) {
        switch (operator) {
            case '+': return a + b;
            case '-': return a - b;
            case '*': return a * b;
            case '/': return a / b;
        }
        return 0;
    }
}
